package com.example.demo.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.example.demo.entity.Role;
import com.example.demo.service.RoleService;
import com.example.demo.service.UserService;
import lombok.AllArgsConstructor;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.LinkedList;
import java.util.List;
import java.util.function.Function;

/**
 * @author 三石
 */

/**
 * UserDetailsService Security提供的用于加载用户密码、权限、角色
 * 最终封装成 UserDetails 对象 返回给 Security
 */
@Service
@AllArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {

    private UserService userService;
    private RoleService roleService;
    /**
     *自定义加载规则
     * @param username 用户名
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //1.获取密码
        String password = userService.findPasswordByUsername(username);
        if (ObjectUtil.isEmpty(username)){
            throw new RuntimeException("密码错误");
        }
//        if (ObjectUtil.isEmpty(username)){
//            throw new BadCredentialsException("密码错误");
//        }

        //2.根据用户名查询角色列表
        List<Role> rolesList = userService.findRolesByUsername(username);
        String[] roleNameList=new String[rolesList.size()];
        LinkedList<Long> roleIds=new LinkedList<>();
        for (int i = 0; i < rolesList.size(); i++) {
            roleNameList[i]=rolesList.get(i).getRolename();
            roleIds.add(rolesList.get(i).getId());
        }
//        LinkedList<Long> roleIds=new LinkedList<>();
//        /* 使用map将stream流循环从role获取roleName并转为字符串集合 */
//        String[] roleNameList = rolesList.stream().map(new Function<Role, String>() {
//            @Override
//            public String apply(Role role) {
//                roleIds.add(role.getId());
//                return role.getRolename();
//            }
//        }).toArray(String[]::new);
        //.toArray(String[]::new) 是 Java 8 中的方法引用（Method Reference）语法，用于创建一个指定类型的数组并将 Stream 中的元素转换为该数组

        //3.根据角色列表查询权限列表
        List<String> authUris = roleService.findAuthByIds(roleIds);
        LinkedList<GrantedAuthority> authorities=new LinkedList<>();
        for (String uri : authUris) {
            authorities.add(new SimpleGrantedAuthority(uri));
        }

        //4.构造出UserDetails对象并返回
        return User.withUsername(username).password(password).roles(roleNameList).authorities(authorities).build();
    }
}
